using System;
using System.Collections.Generic;
using System.Linq;
using Urs.Core;
using Urs.Core.Caching;
using Urs.Core.Data;
using Urs.Data.Domain.Localization;
using Urs.Data;
using Urs.Data.Domain.Configuration;
using Urs.Services.Logging;

namespace Urs.Services.Localization
{
    public partial class LocalizationService : ILocalizationService
    {
        #region Constants
        private const string LOCALSTRINGRESOURCES_ALL_KEY = "Urs.lsr.all";
        private const string LOCALSTRINGRESOURCES_BY_RESOURCENAME_KEY = "Urs.lsr.{0}";
        private const string LOCALSTRINGRESOURCES_PATTERN_KEY = "Urs.lsr.";
        #endregion

        #region Fields

        private readonly IRepository<LocaleStringResource> _lsrRepository;
        private readonly IWorkContext _workContext;
        private readonly ILogger _logger;
        private readonly ICacheManager _cacheManager;
        private readonly IDataProvider _dataProvider;
        private readonly IDbContext _dbContext;
        private readonly CommonSettings _commonSettings;

        #endregion

        #region Ctor

        public LocalizationService(ICacheManager cacheManager,
            ILogger logger, IWorkContext workContext,
            IRepository<LocaleStringResource> lsrRepository,

            IDataProvider dataProvider, IDbContext dbContext, CommonSettings commonSettings)
        {
            this._cacheManager = cacheManager;
            this._logger = logger;
            this._workContext = workContext;
            this._lsrRepository = lsrRepository;

            this._dataProvider = dataProvider;
            this._dbContext = dbContext;
            this._commonSettings = commonSettings;
            this._dataProvider = dataProvider;
            this._dbContext = dbContext;
            this._commonSettings = commonSettings;
        }

        #endregion

        #region Methods

        public virtual void DeleteLocaleStringResource(LocaleStringResource localeStringResource)
        {
            if (localeStringResource == null)
                throw new ArgumentNullException("localeStringResource");

            _lsrRepository.Delete(localeStringResource);

            _cacheManager.RemoveByPattern(LOCALSTRINGRESOURCES_PATTERN_KEY);
        }

        public virtual LocaleStringResource GetLocaleStringResourceById(int localeStringResourceId)
        {
            if (localeStringResourceId == 0)
                return null;

            var localeStringResource = _lsrRepository.GetById(localeStringResourceId);
            return localeStringResource;
        }

        public virtual LocaleStringResource GetLocaleStringResourceByName(string resourceName)
        {
            return GetLocaleStringResourceByName(resourceName, true);
        }

        public virtual LocaleStringResource GetLocaleStringResourceByName(string resourceName,
            bool logIfNotFound = true)
        {
            var query = from lsr in _lsrRepository.Table
                        orderby lsr.Name
                        where lsr.Name == resourceName
                        select lsr;
            var localeStringResource = query.FirstOrDefault();

            return localeStringResource;
        }

        public virtual IList<LocaleStringResource> GetAllResources()
        {
            var query = from l in _lsrRepository.Table
                        orderby l.Name
                        select l;
            var locales = query.ToList();
            return locales;
        }

        public virtual void InsertLocaleStringResource(LocaleStringResource localeStringResource)
        {
            if (localeStringResource == null)
                throw new ArgumentNullException("localeStringResource");

            _lsrRepository.Insert(localeStringResource);

            _cacheManager.RemoveByPattern(LOCALSTRINGRESOURCES_PATTERN_KEY);

        }

        public virtual void UpdateLocaleStringResource(LocaleStringResource localeStringResource)
        {
            if (localeStringResource == null)
                throw new ArgumentNullException("localeStringResource");

            _lsrRepository.Update(localeStringResource);

            _cacheManager.RemoveByPattern(LOCALSTRINGRESOURCES_PATTERN_KEY);
        }

        public virtual void AddOrUpdatePluginLocaleResource(string resourceName, string resourceValue)
        {
            var lsr = GetLocaleStringResourceByName(resourceName);
            if (lsr == null)
            {
                lsr = new LocaleStringResource
                {
                    Name = resourceName,
                    Value = resourceValue
                };
                InsertLocaleStringResource(lsr);
            }
            else
            {
                lsr.Value = resourceValue;
                UpdateLocaleStringResource(lsr);
            }
        }

        public virtual void DeletePluginLocaleResource(string resourceName)
        {
            var lsr = GetLocaleStringResourceByName(resourceName);
            if (lsr != null)
                DeleteLocaleStringResource(lsr);

        }

        public virtual Dictionary<string, KeyValuePair<int, string>> GetAllResourceValues()
        {
            string key = LOCALSTRINGRESOURCES_ALL_KEY;
            return _cacheManager.Get(key, () =>
            {
                var query = from l in _lsrRepository.Table
                            orderby l.Name
                            select l;
                var locales = query.ToList();
                var dictionary = new Dictionary<string, KeyValuePair<int, string>>();
                foreach (var locale in locales)
                {
                    var resourceName = locale.Name.ToLowerInvariant();
                    if (!dictionary.ContainsKey(resourceName))
                        dictionary.Add(resourceName, new KeyValuePair<int, string>(locale.Id, locale.Value));
                }
                return dictionary;
            });
        }

        public virtual string GetResource(string resourceKey)
        {
            return GetResource(resourceKey, true, "", false);
        }

        public virtual string GetResource(string resourceKey,
            bool logIfNotFound = true, string defaultValue = "", bool returnEmptyIfNotFound = false)
        {
            string result = string.Empty;
            if (resourceKey == null)
                resourceKey = string.Empty;
            resourceKey = resourceKey.Trim().ToLowerInvariant();

            var resources = GetAllResourceValues();
            if (resources.ContainsKey(resourceKey))
            {
                result = resources[resourceKey].Value;
            }

            if (String.IsNullOrEmpty(result))
            {
                if (!String.IsNullOrEmpty(defaultValue))
                {
                    result = defaultValue;
                }
                else
                {
                    if (!returnEmptyIfNotFound)
                        result = resourceKey;
                }
            }
            return result;
        }

        #endregion
    }
}
